package com.sjf.JavaNIO.asyncfilechannel;

import org.junit.Test;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;

/**
 * 异步文件通道对文件进行异步操作
 * 1、异步文件通道有两种方式问文件进行读写操作
 * 2.Future操作方式可以在操作未完成前做一些操作，而Complete只有开始状态和结束状态，无法在中间状态做操作
 *
 * @author <huangtang>
 * @since 2022/4/16 10:25
 **/
public class AsyncFileChannelDemo {

    /**
     * complete写操作到文件通道中
     */
    @Test
    public void writeAsyncFileComplete () throws IOException {
        Path path = Paths.get ("D:\\atguigu\\test\\01.txt");
        //1.创建AsyncFileChannel
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open (path , StandardOpenOption.WRITE);
        //2.创建buffer
        ByteBuffer buffer = ByteBuffer.allocate (1024);
        buffer.put ("buffer111".getBytes (StandardCharsets.UTF_8));
        buffer.flip ();
        fileChannel.write (buffer , 0 , buffer , new CompletionHandler<Integer, ByteBuffer> () {
            @Override
            public void completed ( Integer result , ByteBuffer attachment ) {
                System.out.println ("result:" + result);
                while (attachment.hasRemaining ()) {
                    System.out.println ((char) attachment.get ());
                }
                attachment.clear ();
                System.out.println ("write over!");
            }

            @Override
            public void failed ( Throwable exc , ByteBuffer attachment ) {

            }
        });
    }

    /**
     * Future写操作到文件通道中
     */
    @Test
    public void writeAsyncFileFuture () throws IOException {
        Path path = Paths.get ("D:\\atguigu\\test\\01.txt");
        //1.创建AsyncFileChannel
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open (path , StandardOpenOption.WRITE);
        //2.创建buffer
        ByteBuffer buffer = ByteBuffer.allocate (1024);
        buffer.put ("hello,sjf!!!".getBytes (StandardCharsets.UTF_8));
        buffer.flip ();
        Future<Integer> future = fileChannel.write (buffer , 0);
        while (!future.isDone ()) ;

        System.out.println ("写操作完成！");
    }

    /**
     * Future读操作
     *
     * @throws IOException
     */
    @Test
    public void readAsyncFileChannelFuture () throws IOException {
        Path path = Paths.get ("D:\\atguigu\\test\\01.txt");
        //1 创建AsyncFileChannel
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open (path , StandardOpenOption.READ);
        //2.创建buffer
        ByteBuffer buffer = ByteBuffer.allocate (1024);
        //3.调用read方法得到Future
        Future<Integer> future = fileChannel.read (buffer , 0);
        //4.判断是否完成
        //此处一直循环，直到read操作完成
        while (!future.isDone ()) ;
        //读取数据到buffer里面
        buffer.flip ();
        while (buffer.hasRemaining ()) {
            System.out.print ((char) buffer.get ());
        }
        buffer.clear ();

    }

    /**
     * Complete读操作
     *
     * @throws IOException
     */
    @Test
    public void readAsyncFileChannelComplete () throws IOException {
        Path path = Paths.get ("D:\\atguigu\\test\\01.txt");
        //1 创建AsyncFileChannel
        AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open (path , StandardOpenOption.READ);
        //2.创建buffer
        ByteBuffer buffer = ByteBuffer.allocate (1024);
        //3.调用read方法得到Future
        fileChannel.read (buffer , 0 , buffer , new CompletionHandler<Integer, ByteBuffer> () {
            //读取完成后执行的方法
            @Override
            public void completed ( Integer result , ByteBuffer attachment ) {
                System.out.println ("result:" + result);
                attachment.flip ();
                while (attachment.hasRemaining ()) {
                    System.out.print ((char) attachment.get ());
                }
            }

            //读取失败后执行的方法
            @Override
            public void failed ( Throwable exc , ByteBuffer attachment ) {

            }
        });

    }
}
